#ifndef _MY_INCLUDE_ASYNCIO_HH_
#define _MY_INCLUDE_ASYNCIO_HH_

#include "asynceventreceiver.hh"
#include <map>

namespace async
{

class io
{
public:
    static io& instance();

    io& registry(
        event_source _fd,
        event_receiver_fnc _handler,
        struct events _watch);
    template < typename context > io& registry(
        event_source _fd,
        std::pair< context*, typename event_receiver_m< context >::fnc > _handler,
        struct events _watch)
    { return this->add(_fd, _watch, _handler); }
    template < typename context > io& registry(
        event_source _fd,
        std::pair< typename event_receiver_m< context >::fnc, context* > _handler,
        struct events _watch)
    { return this->add(_fd, _watch, _handler); }

    io& change(
        event_source _fd,
        struct events _watch);
    io& change(
        event_source _fd,
        event_receiver_fnc _handler,
        struct events _watch);
    template < typename context > io& change(
        event_source _fd,
        std::pair< context*, typename event_receiver_m< context >::fnc > _handler,
        struct events _watch)
    { return this->mod(_fd, _watch, _handler); }
    template < typename context > io& change(
        event_source _fd,
        std::pair< typename event_receiver_m< context >::fnc, context* > _handler,
        struct events _watch)
    { return this->mod(_fd, _watch, _handler); }

    io& free(event_source _fd);
    io& on_close(event_source _fd);

    io& operator()();
private:
    io();
    io(const io&);
    ~io();
    io& operator=(const io&);

    io& add(event_source _fd, struct events _watch, const event_receiver &_handler);
    io& mod(event_source _fd, struct events _watch);
    io& mod(event_source _fd, struct events _watch, const event_receiver &_handler);
    io& del(event_source _fd);

    static void normal_add(io *_this, event_source _fd, struct events _watch, const event_receiver &_handler);
    static void normal_mod(io *_this, event_source _fd, struct events _watch);
    static void normal_mod(io *_this, event_source _fd, struct events _watch, const event_receiver &_handler);
    static void normal_del(io *_this, event_source _fd);

    static void running_add(io *_this, event_source _fd, struct events _watch, const event_receiver &_handler);
    static void running_mod(io *_this, event_source _fd, struct events _watch);
    static void running_mod(io *_this, event_source _fd, struct events _watch, const event_receiver &_handler);
    static void running_del(io *_this, event_source _fd);

    class swap_running;

    typedef void (*fnc_add)(io*, event_source, struct events, const event_receiver&);
    typedef void (*fnc_mod_watch)(io*, event_source, struct events);
    typedef void (*fnc_mod)(io*, event_source, struct events, const event_receiver&);
    typedef void (*fnc_del)(io*, event_source);

    typedef std::map< event_source, event_receiver > receiver;

    file_descriptor epd_; // epoll descriptor

    receiver receiver_;

    fnc_add invoke_add_;
    fnc_mod_watch invoke_mod_watch_;
    fnc_mod invoke_mod_;
    fnc_del invoke_del_;
};

}

#endif//_MY_INCLUDE_ASYNCIO_HH_
